
from lib import world
from lib import commands
from lib import net
from lib import log

import Player

class GameWorld(world.World):
    """
    GameWorld class.
    """
    def __init__(self, gamePackageName, **args):
        super(GameWorld, self).__init__(gamePackageName)
        ## any other SampleWorld specific initialization
        self._commandManager = commands.CommandManager(self)
        self._connections = list()
        self._players = list()
        self._connectionToPlayerMap = dict()
        self._playerToConnectionMap = dict()
        self._rooms = dict()
        
    @property
    def commandManager(self): return self._commandManager
    @property
    def connections(self): return self._connections
    @property
    def players(self): return self._players
    
    def playerForConnection(self, connection):
        return self._connectionToPlayerMap.get(connection.connectionId)
    
    def connectionForPlayer(self, player):
        return self._playerToConnectionMap.get(player.playerId)
    
    def roomWithAddress(self, roomAddress):
        if roomAddress in self._rooms:
            return self._rooms[roomAddress]
        else:
            full_address = "map." + roomAddress
            new_room_class = self.loadObject(full_address)
            room = None
            if new_room_class:
                room = new_room_class(self)
                self._rooms[roomAddress] = room
            else:
                log.error("no room with address {0}".format(full_address))
            return room
    
    def connect(self, connection):
        log.debug("connect called for connection {0} id={1}".format(connection, hex(id(connection))))
        self._connections.append(connection)
        player = Player.Player('test', connection, self.roomWithAddress('main.Start'), self)
        self._connectionToPlayerMap[connection.connectionId] = player
        self._playerToConnectionMap[player.playerId] = connection
        self.playerStartMessage(player)
        
    def disconnect(self, connection):
        log.debug("disconnect called for connection {0} id={1}".format(connection, hex(id(connection))))
        if not connection in self._connections:
            log.debug("Ignoring -- connection {0} unknown".format(hex(id(connection))))
            return
        player = self.playerForConnection(connection)
        if player:
            self.playerQuitMessage(player)
            if player.location:
                player.location.objectLeft(player, None)
            del self._playerToConnectionMap[player.playerId]
        self._connections.remove(connection)
        del self._connectionToPlayerMap[connection.connectionId]
        connection.sendDisconnectToClient()
        connection.stop()

    def consoleCommand(self, player, command):
        command_tokens = commands.CommandManager.tokenize(command)
        self.commandManager.executeCommand(None, command_tokens[0], command_tokens)
        
    def networkCommand(self, connection, command):
        player = self.playerForConnection(connection)
        command_tokens = commands.CommandManager.tokenize(command)
        if player.location:
            if player.location.hasCommand(command_tokens[0]):
                player.location.executeCommand(player, command_tokens[0], command_tokens)
                return
        # otherwise see if this is a global command
        self.commandManager.executeCommand(player, command_tokens[0], command_tokens)
        
    def playerStartMessage(self, player):
        player.message("Welcome to the Sample game.")
        player.message("\"Where probably none of your dreams will come true.\"(TM)")
        player.notify("{0} steps out of a mysterious cloud of dust".format(player.name))
        
    def playerQuitMessage(self, player):
        player.message("<insert corny goodbye message here>")
        player.notify("{0} disappears in a mysterious cloud of dust.".format(player.name))
    
    def notifyAll(self, message):
        for player in self.players.iteritems():
            player.message(message)
    
